ROS 2 Humble 기반 드론 개발을 위한 nvblox_ros 예제

ROS 2 Humble 기반 드론 개발을 위한 nvblox_ros 예제

1. 서론

자율 드론이 GPS 신호가 불안정하거나 도달하지 않는 실내, 복잡한 도심 협곡과 같은 환경에서 임무를 성공적으로 수행하기 위해서는 주변 환경을 실시간으로 3차원으로 인식하고 재구성하는 능력이 필수적이다.1 이러한 3D 환경 정보는 드론이 장애물을 회피하고 안전하며 효율적인 경로를 계획하는 데 결정적인 역할을 한다.3 기존의 CPU 기반 3D 재구성 방식은 드론과 같이 계산 자원이 제한적이고 실시간성이 극도로 중요한 플랫폼에서는 성능의 한계를 보여왔다.

이러한 문제를 해결하기 위해 NVIDIA Isaac ROS는 nvblox_ros라는 고성능 ROS 2 패키지를 제공한다.4

nvblox_ros는 NVIDIA GPU의 강력한 병렬 처리 능력을 활용하여 깊이(Depth) 카메라나 3D LiDAR 센서로부터 얻은 데이터와 드론의 자세(Pose) 정보를 실시간으로 정밀한 3D 맵으로 변환한다.6 이는 드론 플랫폼에 최적화된 3D 환경 인식 솔루션을 제공한다.

본 안내서는 nvblox_ros의 기술적 근간을 이루는 핵심 원리를 심층적으로 분석하고, ROS 2 시스템과의 연동 아키텍처를 파악하며, NVIDIA Isaac Sim 시뮬레이터를 활용한 구체적인 드론 적용 예제를 단계별로 제시하는 것을 목표로 한다. 이를 통해 독자는 nvblox의 이론적 이해를 바탕으로 실제 드론 개발 프로젝트에 이 기술을 성공적으로 통합하고 활용하는 데 필요한 모든 지식을 얻게 될 것이다.

2. nvblox의 핵심 원리: TSDF와 ESDF

nvblox의 성능과 기능은 Truncated Signed Distance Field (TSDF)와 Euclidean Signed Distance Field (ESDF)라는 두 가지 핵심적인 데이터 표현 방식에 기반한다. 이 두 가지 방식은 단순한 3D 모델링을 넘어, 로봇의 경로 계획에 직접적으로 활용될 수 있는 풍부한 정보를 제공한다.

2.1 Truncated Signed Distance Field (TSDF) 심층 분석

TSDF는 3차원 공간을 일정한 크기의 복셀(Voxel) 그리드로 나누고, 각 복셀의 중심점에서 가장 가까운 표면(surface)까지의 부호화된 거리(Signed Distance)를 저장하는 방식이다.1 여기서 ‘부호화된’ 거리란, 복셀이 표면의 바깥쪽(free space)에 있으면 양수 값을, 안쪽(occupied space)에 있으면 음수 값을 갖는 것을 의미한다. 이 방식은 단순히 점유/비점유 상태의 이진 정보만을 저장하는 점유 격자 맵(Occupancy Grid Map)에 비해 훨씬 더 정밀하고 연속적인 표면 재구성을 가능하게 한다.1

수학적으로 특정 복셀 x에서의 TSDF 값 D(x)는 다음과 같이 정의할 수 있다.
D(x) = \max \left(-1, \min \left(1, \frac{d(x)}{\tau}\right) \right)
위 식에서 d(x)는 복셀 중심에서 가장 가까운 표면까지의 실제 부호화된 거리를 의미하며, \tau는 ’절단 거리(truncation distance)’라는 중요한 파라미터이다. TSDF는 이 절단 거리 \tau 내에 있는 복셀들의 거리 값만 저장하고, 그보다 멀리 있는 복셀들의 값은 −1 또는 1로 고정(truncate)한다. 이를 통해 연산량과 메모리 사용량을 표면 주변의 관심 영역에만 집중시켜 효율성을 극대화한다.

새로운 깊이 이미지 프레임이 입력될 때마다, 각 복셀의 TSDF 값과 가중치(weight)는 가중 평균(weighted average) 방식을 통해 점진적으로 갱신된다.8 이 과정은 센서 노이즈를 자연스럽게 필터링하고, 여러 관점에서 얻은 정보를 통합하여 시간이 지남에 따라 더욱 정확하고 일관된 표면 모델을 구축하게 한다.10 수식은 다음과 같다.
D_{k+1}(x) = \frac{W_k(x)D_k(x) + w_{k+1}(x)d_{k+1}(x)}{W_k(x) + w_{k+1}(x)}

W_{k+1}(x) = W_k(x) + w_{k+1}(x)

여기서 D_k(x)W_k(x)k번째 시점까지 누적된 TSDF 값과 가중치이며, d_{k+1}(x)w_{k+1}(x)는 새로 들어온 (k+1)번째 관측에 의한 거리 값과 가중치이다. voxel_sizetruncation_distance(\tau)는 TSDF 맵의 품질과 성능을 결정하는 가장 핵심적인 파라미터로, voxel_size는 맵의 해상도를, truncation_distance는 표면 주변 정보를 얼마나 두텁게 저장할지를 결정한다.11

2.2 Euclidean Signed Distance Field (ESDF)의 생성과 활용

ESDF는 TSDF로부터 파생되는 매우 유용한 데이터 구조이다. TSDF가 표면 근처의 정보만 절단하여 저장하는 반면, ESDF는 맵 상의 모든 지점에서 가장 가까운 장애물(표면)까지의 절단되지 않은 실제 유클리드 거리(Euclidean Distance) 정보를 제공한다.1

이러한 특성은 ESDF를 ’계획 친화적(Planning-Friendly)’인 맵 표현 방식으로 만든다. 전통적인 점유 격자 맵이 특정 지점이 “갈 수 있는가/없는가“의 이진 정보만 제공하는 반면, ESDF는 “장애물로부터 얼마나 떨어져 있는가“라는 연속적인 안전 거리 정보를 즉시 제공한다. 경로 계획 알고리즘은 이 정보를 활용하여 잠재적 경로상의 각 지점에 대한 충돌 위험도를 비용(cost)으로 즉시 계산할 수 있으며, 이는 안전하고 부드러운 경로를 생성하는 데 결정적이다.1

nvblox가 ESDF를 생성한다는 사실은 이 패키지가 단순한 3D 시각화를 넘어, ROS 2 Nav2와 같은 고급 자율 항법 스택과의 긴밀한 통합을 염두에 두고 설계되었음을 보여준다.4

nvblox는 TSDF 맵에서 표면에 해당하는 복셀들(TSDF 값이 0에 가까운 복셀)을 ’사이트(sites)’로 지정하고, 이 사이트로부터 주변의 빈 공간(free space) 복셀들로 거리 정보를 파도처럼 전파(propagation)시키는 알고리즘을 통해 ESDF를 생성한다. 이 알고리즘은 CPU 기반의 선행 연구인 Voxblox에서 영감을 받았으며, nvblox에서는 GPU의 병렬 처리 아키텍처에 맞게 최적화되어 매우 빠른 속도로 수행된다.7 생성된 3D ESDF는 특정 고도의 2D 평면으로 잘라내어(slice) Nav2 스택의 비용 맵(Costmap)으로 직접 공급될 수 있으며, 이를 통해 드론은 현재 비행 고도에 맞춰 실시간으로 장애물을 회피하는 경로를 계획할 수 있다.4

2.3 GPU 가속의 역할

nvblox의 실시간 성능은 NVIDIA CUDA 기술을 통한 GPU 가속에 힘입은 바가 크다.6 TSDF 값을 통합하고 ESDF를 생성하는 과정은 수많은 복셀에 대해 독립적인 계산을 반복하는 작업으로, 이는 본질적으로 병렬 처리에 매우 적합하다.

nvblox는 이러한 복셀 단위 연산들을 수천 개의 GPU 코어에서 동시에 처리함으로써 CPU 기반 라이브러리 대비 수십에서 수백 배에 달하는 압도적인 성능 향상을 이뤄냈다.7 이러한 성능 우위는 고해상도 깊이 센서 데이터를 지연 없이 처리해야 하는 드론과 같은 실시간 로보틱스 애플리케이션에 nvblox를 가장 적합한 솔루션으로 만드는 결정적인 요인이다.5

3. nvblox_ros 시스템 아키텍처 및 ROS 2 연동

nvblox_ros는 핵심 라이브러리인 nvblox를 ROS 2 생태계에 통합하기 위한 래퍼(wrapper) 패키지이다. 이는 ROS 2의 표준 인터페이스인 토픽, 서비스, 파라미터를 통해 다른 노드들과 상호작용하며, 전체 로봇 시스템의 한 부분으로 기능한다.

3.1 노드, 토픽, 서비스 분석

nvblox_ros 패키지의 중심에는 nvblox_node가 있다.17 이 단일 노드는 센서 데이터 구독, nvblox C++ 라이브러리를 이용한 맵 처리, 그리고 재구성된 맵 정보 발행에 이르는 모든 데이터 처리 파이프라인을 관리한다.19 일반적인 데이터 흐름은 다음과 같다: (깊이 이미지 + 카메라 정보)와 (드론의 자세/TF)가 nvblox_node에 입력되면, 노드는 이를 처리하여 (3D 메시, ESDF 맵 슬라이스, Nav2용 비용 맵) 등을 출력 토픽으로 발행한다. 만약 동적 객체(예: 사람)를 처리하는 모드를 활성화하면, 컬러 이미지와 의미론적 분할(Semantic Segmentation) 마스크 이미지가 추가 입력으로 필요하다.4

nvblox_node의 주요 입출력 인터페이스는 아래 표와 같다. 이 표는 nvblox를 카메라 드라이버, SLAM 시스템, 경로 계획기와 같은 다른 ROS 2 노드와 연결하기 위한 아키텍처 청사진 역할을 한다.

Table 1: nvblox_node 주요 구독/발행 토픽 및 서비스

구분이름 (기본값)메시지 타입설명관련 Snippet
구독 (Inputs)depth/imagesensor_msgs::msg::Image깊이 이미지. 픽셀 값은 미터 단위의 거리를 나타내야 함.4
depth/camera_infosensor_msgs::msg::CameraInfo깊이 카메라의 내부 파라미터(Intrinsics).19
color/imagesensor_msgs::msg::Image컬러 이미지. 동적 객체(사람) 분리에 사용됨.4
color/camera_infosensor_msgs::msg::CameraInfo컬러 카메라의 내부 파라미터.19
mask/imagesensor_msgs::msg::Image의미론적 분할(Semantic Segmentation) 마스크.4
posegeometry_msgs::msg::PoseStampedglobal_frame에 대한 센서의 자세. use_topic_transforms가 false일 때 사용.4
/tf, /tf_statictf2_msgs::msg::TFMessageglobal_framepose_frame 간의 변환. use_topic_transforms가 true일 때 사용.11
발행 (Outputs)meshnvblox_msgs::msg::Mesh재구성된 3D 메시. RViz 시각화에 사용됨.17
map_slicenvblox_msgs::msg::DistanceMapSliceESDF의 2D 슬라이스. Nav2 비용 맵 플러그인 입력용.17
esdf_pointcloudsensor_msgs::msg::PointCloud22D ESDF를 시각화하기 위한 포인트 클라우드.17
costmap/voxel_gridnav2_msgs::msg::VoxelGridNav2에서 사용할 3D 비용 맵 (Voxel Layer).4
static_occupancysensor_msgs::msg::PointCloud2정적 환경의 점유 상태를 나타내는 포인트 클라우드.11
서비스~/save_mapnvblox_msgs::srv::FilePath현재 맵을 파일로 저장.5
~/load_mapnvblox_msgs::srv::FilePath파일로부터 맵을 로드.5

3.2 핵심 파라미터 설정 가이드

nvblox_node의 동작 방식은 YAML 형식의 설정 파일을 통해 세밀하게 제어된다.21 일반적으로 nvblox_base.yaml 파일에 모든 환경에 공통적으로 적용되는 기본 설정을 정의하고, 특정 센서나 임무에 맞는 특화된 설정은 별도의 YAML 파일로 분리하여 관리하는 것이 효율적이다.11

드론 애플리케이션에서 nvblox의 성능을 최적화하기 위해 반드시 이해하고 조정해야 할 핵심 파라미터들은 다음과 같다. 이 표는 nvblox를 단순한 블랙박스가 아닌, 특정 요구사항에 맞게 튜닝할 수 있는 강력한 도구로 사용하는 데 필수적인 가이드이다.

Table 2: nvblox_ros 핵심 ROS 파라미터

파라미터타입기본값설명튜닝 가이드 (드론)관련 Snippet
General
global_framestring“map”맵이 생성되는 고정 좌표계.드론의 VIO/SLAM이 발행하는 odom 또는 map 프레임으로 설정.11
pose_framestring“base_link”입력 자세(pose)의 기준이 되는 좌표계.드론의 베이스 좌표계(예: base_link)로 설정.11
use_topic_transformsbooltruetrue이면 TF를, false이면 pose 토픽을 자세 입력으로 사용.실시간성이 중요한 드론에서는 TF 사용을 권장.25
Mapper
voxel_sizedouble0.05복셀의 크기 (미터). 맵의 해상도와 성능을 결정.실내 정밀 탐사는 0.02~0.05, 실외 고속 비행은 0.1 이상으로 설정하여 부하 조절.5
mapping_typestring“static”매핑 모드. “static”, “people_segmentation”, “dynamic” 중 선택.사람이나 움직이는 물체가 많은 환경에서는 “dynamic” 모드 사용 고려.4
esdf_modestring“2d”ESDF 생성 모드. “2d”, “3d” 중 선택.2D 평면 경로 계획이 주 목적이면 “2d“가 효율적. 3D 경로 계획 시 “3d” 필요.16
ESDF Slicing
slice_heightdouble0.0ESDF 2D 슬라이스를 추출할 높이 (미터).드론의 비행 고도에 맞춰 동적으로 변경하거나, 주 비행 고도로 설정.16
max_esdf_update_hzdouble5.0ESDF 맵의 최대 업데이트 주기 (Hz).경로 계획 주기에 맞춰 설정. 높이면 반응성이 좋아지나 부하 증가.17
Meshing
max_mesh_update_hzdouble5.03D 메시의 최대 업데이트 주기 (Hz).시각화용이므로, 대역폭 확보를 위해 1.0 이하로 낮추는 것을 권장.11

nvblox의 성공적인 운영은 잘 구성된 TF(Transform) 트리에 크게 의존한다. nvbloxglobal_frame(예: map)을 기준으로 pose_frame(예: base_link)의 시시각각 변하는 위치와 방향을 정확히 알아야만, 여러 시점에서 관측된 센서 데이터를 올바른 위치에 누적하여 일관된 맵을 만들 수 있다.11 이 변환 정보는 주로 ROS의 TF 시스템을 통해 전달된다. 만약 드론의 자세를 추정하는 VSLAM 노드가 발행하는 TF 정보가 불안정하거나, 특정 변환 관계가 누락되거나, 타임스탬프가 일치하지 않으면 nvblox는 입력을 제대로 처리하지 못하고 심하게 왜곡된 맵을 생성하게 된다.16 따라서 nvblox 관련 문제를 디버깅할 때는 nvblox_node 자체의 로그를 보기 전에, 먼저 RViz와 같은 시각화 도구에서 TF 트리가 의도한 대로 끊김 없이 안정적으로 연결되어 있는지 확인하는 것이 가장 효율적인 문제 해결의 첫걸음이다.

4. 개발 환경 구축 및 설치

nvblox_ros는 고성능 GPU 라이브러리에 깊이 의존하므로, 안정적인 개발 환경을 구축하는 것이 매우 중요하다.

4.1 시스템 요구사항

nvblox_ros는 ROS 2 Humble 배포판을 공식 지원하며, NVIDIA Jetson Orin 시리즈 또는 NVIDIA GPU가 장착된 x86_64 아키텍처의 리눅스 시스템에서 구동되도록 설계 및 테스트되었다.5 소프트웨어적으로는 Ubuntu 22.04, CUDA 12.6 이상 버전이 필요하며, 개발 환경으로는 Docker 사용이 강력히 권장된다.5 하드웨어 측면에서는, Jetson Orin Nano 4GB 모델은 메모리 부족 문제로 권장되지 않으며, x86_64 시스템의 경우 최소 8GB 이상의 VRAM을 갖춘 Ampere 아키텍처 이상의 NVIDIA GPU가 필요하다.5

4.2 Docker 기반 설치 절차 (권장)

nvblox는 CUDA, VPI, TensorRT 등 복잡하고 버전 민감도가 높은 NVIDIA 라이브러리 스택에 의존한다. Docker는 이러한 모든 의존성을 사전 설치하고 격리된 컨테이너 환경을 제공함으로써, 호스트 시스템의 설정과 충돌 없이 신속하고 안정적으로 개발 환경을 구축하는 가장 효과적인 방법이다.26

  1. isaac_ros_common 클론: ROS 2 워크스페이스를 생성하고, run_dev.sh 스크립트를 포함한 공통 유틸리티를 확보하기 위해 isaac_ros_common 저장소를 먼저 클론한다.26
  2. isaac_ros_nvblox 클론: nvblox_ros 패키지를 소스 코드로 설치하기 위해 저장소를 클론한다. 이때 반드시 --recursive 옵션을 사용하여 nvblox_core와 같은 핵심 C++ 라이브러리 서브모듈을 함께 다운로드해야 한다.26
  3. Docker 컨테이너 실행: isaac_ros_common/scripts/run_dev.sh 스크립트를 실행하여 Isaac ROS 개발용 Docker 컨테이너를 시작하고 내부 셸에 진입한다.26
  4. 의존성 설치 및 빌드: 컨테이너 내부에서 rosdep install 명령을 실행하여 nvblox_ros에 필요한 모든 ROS 패키지 의존성을 설치한다. 그 후, colcon build 명령으로 전체 워크스페이스를 컴파일한다.26

공식 문서에서는 ‘Debian에서 설치’ (apt-get install...)와 ‘소스에서 설치’ (git clone...) 두 가지 방법을 제시하는데, 이는 각각의 사용 목적이 다르다는 점을 이해해야 한다.26 Debian 설치는 사전 컴파일된 바이너리를 사용하는 방식으로, nvblox를 수정 없이 그대로 사용하려는 경우나 최종 제품에 배포할 때 빠르고 편리하다. 반면, 소스 설치는 개발자가 직접 코드를 컴파일하는 방식으로, 코드 수정, 디버깅, 또는 세부 파라미터 튜닝이 필요한 개발 단계에 필수적이다. 따라서 이 안내서의 독자인 개발자에게는 소스 설치 방식이 더 적합하다.

4.3 일반적인 빌드 오류 및 해결 방안

  • CMAKE_CUDA_ARCHITECTURES 오류: 주로 네이티브 환경에서 CUDA 툴킷이 올바르게 설치되지 않았거나, CMake가 NVCC 컴파일러를 찾지 못할 때 발생한다. PATHLD_LIBRARY_PATH 환경 변수에 CUDA 관련 경로가 올바르게 설정되었는지 확인해야 한다.27
  • Could not find requested resource in ament index 오류: colcon build 과정에서 특정 패키지가 실패했거나, 빌드 성공 후 source install/setup.bash 명령을 실행하지 않아 ROS 2 시스템이 새로 빌드된 노드를 인식하지 못하는 경우에 발생한다.29
  • rosdep 실패: rosdep update 실행 시 404 오류 등이 발생하면, 일시적인 네트워크 문제이거나 ROS 패키지 서버의 문제일 수 있다. 잠시 후 다시 시도하거나 프록시 설정을 확인해야 한다.27

5. Isaac Sim을 이용한 드론 시뮬레이션 예제

NVIDIA Isaac Sim은 물리적으로 정확한 시뮬레이션과 사실적인 센서 데이터 생성이 가능한 강력한 로보틱스 시뮬레이터이다. 이를 활용하면 값비싼 실제 드론 하드웨어 없이도 nvblox_ros를 포함한 전체 자율 비행 스택을 안전하고 효율적으로 개발 및 테스트할 수 있다.

5.1 시뮬레이션 환경 및 드론 모델 설정

  1. Isaac Sim 실행 및 환경 구성: isaac-sim.sh 스크립트로 시뮬레이터를 실행한 후, File > New를 통해 새로운 Stage를 생성한다. 기본적인 비행 환경을 위해 Create > Physics > Ground Plane으로 바닥을, Create > Light 메뉴를 통해 조명을 추가한다.30
  2. 드론 에셋 로드: Stage에 가상 드론을 배치한다. Isaac Sim은 Carter와 같은 기본 로봇 모델을 제공하지만, 커뮤니티에서 개발한 Pegasus Simulator와 같은 드론 특화 프레임워크를 사용하거나, PX4 SITL과 연동하기 위한 URDF/SDF 파일을 직접 임포트할 수도 있다.15
  3. 가상 센서 추가 및 설정: 드론 모델의 Prim(객체)에 Create > Isaac > Sensors 메뉴를 통해 CameraIMU 센서를 부착한다. 카메라는 Render Product 타입을 depth로 설정하여 깊이 정보를 얻을 수 있도록 하고, 해상도, 시야각(FOV), 측정 가능 거리 등의 파라미터를 실제 드론에 장착할 센서의 사양과 유사하게 맞추는 것이 중요하다.15

5.2 ROS 2 브릿지 설정 및 데이터 파이프라인 구축

Isaac Sim은 시뮬레이터 내부의 데이터와 외부 ROS 2 시스템 간의 통신을 위한 강력한 ROS 2 브릿지 기능을 내장하고 있다.

  1. ROS 2 브릿지 활성화: Create > Visual Scripting > Action Graph를 열고, ROS 2 관련 노드들(예: On Playback Tick, ROS2 Context, ROS2 Publish Camera Info, ROS2 Publish Image 등)을 추가하고 연결하여 ROS 2 통신 파이프라인을 구성한다.15
  2. 토픽 발행 설정: Action Graph 내에서 각 센서의 출력 데이터를 원하는 ROS 2 토픽으로 발행하도록 설정한다. 예를 들어, 깊이 카메라의 데이터는 /sim/depth/image/sim/depth/camera_info 토픽으로, IMU 데이터는 /sim/imu 토픽으로 발행하도록 설정할 수 있다.
  3. VSLAM 연동: 시뮬레이션에서 발행된 이미지와 IMU 데이터는 isaac_ros_visual_slam 노드의 입력으로 사용된다. 이 VSLAM 노드는 드론의 자세를 추정하여 map 좌표계에서 base_link 좌표계로의 TF 변환 정보를 발행하며, 이 정보가 바로 nvblox_ros의 핵심 입력이 된다.2

이 과정은 Isaac Sim을 단순한 3D 뷰어가 아닌, 물리적으로 정확한 센서 데이터를 생성하는 ’데이터 생성기’이자, ROS 2 노드들과 직접 상호작용하는 ’통합 개발 환경’으로 활용하는 핵심 단계이다. 시뮬레이션에서 완벽하게 동작하도록 검증된 ROS 2 노드 구성, 파라미터, launch 파일은 최소한의 수정만으로 실제 하드웨어에 이식될 수 있는 ‘Sim-to-Real’ 워크플로우를 가능하게 한다.15

5.3 nvblox_ros 실행 Launch 파일 작성 및 분석

시뮬레이션 환경에서 VSLAM과 nvblox를 포함한 전체 시스템을 한번에 실행하기 위해 Python 기반의 ROS 2 Launch 파일을 작성한다.

# Conceptual drone_nvblox_sim.launch.py
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
# Load parameters from YAML file
nvblox_params_file = os.path.join(
get_package_share_directory('my_drone_bringup'),
'config',
'drone_nvblox_params.yaml'
)

# VSLAM Node
vslam_node = Node(
package='isaac_ros_visual_slam',
executable='isaac_ros_visual_slam',
name='visual_slam_node',
remappings=[
('stereo_camera/left/image', '/sim/left/image'),
('stereo_camera/left/camera_info', '/sim/left/camera_info'),
('stereo_camera/right/image', '/sim/right/image'),
('stereo_camera/right/camera_info', '/sim/right/camera_info'),
]
)

# Nvblox Node
nvblox_node = Node(
package='nvblox_ros',
executable='nvblox_node',
name='nvblox_node',
parameters=[nvblox_params_file],
remappings=[
('depth/image', '/sim/depth/image'),
('depth/camera_info', '/sim/depth/camera_info'),
('color/image', '/sim/rgb/image'),
('color/camera_info', '/sim/rgb/camera_info'),
]
)

# RViz2 Node
rviz_node = Node(
package='rviz2',
executable='rviz2',
name='rviz2',
arguments=['-d', os.path.join(
get_package_share_directory('my_drone_bringup'),
'rviz',
'nvblox.rviz'
)]
)

return LaunchDescription([vslam_node, nvblox_node, rviz_node])

이 launch 파일은 VSLAM 노드, nvblox_node, RViz 노드를 실행한다. 핵심은 remappings 인자를 사용하여 각 노드의 입출력 토픽을 시뮬레이션 환경에 맞게 연결하는 것이다. 예를 들어, Isaac Sim이 발행하는 /sim/depth/image 토픽을 nvblox_node가 구독하는 /depth/image 토픽으로 리매핑한다. 또한, parameters 인자를 통해 앞서 튜닝한 drone_nvblox_params.yaml 파일을 nvblox_node에 로드한다.22

5.4 RViz를 이용한 결과 시각화 및 분석

RViz는 nvblox의 출력을 시각적으로 확인하고 분석하는 데 필수적인 도구이다.

  1. RViz 설정: RViz를 실행하고 Global OptionsFixed Framenvbloxglobal_frame 파라미터와 동일하게(예: map) 설정한다.
  2. 디스플레이 추가:
  • TF: map, odom, base_link, camera_link 등 좌표계 간의 관계와 드론의 움직임을 시각적으로 확인한다.
  • Mesh: nvblox_msgs::msg::Mesh 타입의 디스플레이를 추가하고 mesh 토픽을 구독하여, 실시간으로 재구성되는 3D 환경 메시를 확인한다. 이를 위해서는 nvblox_rviz_plugin이 설치되어 있어야 한다.17
  • PointCloud2: esdf_pointcloud 또는 static_occupancy 토픽을 구독하여 ESDF의 거리 정보나 복셀의 점유 상태를 포인트 클라우드 형태로 시각화한다.11

6. 실제 드론 적용 시 고려사항 및 심화 주제

시뮬레이션에서 검증된 시스템을 실제 드론에 성공적으로 이식하기 위해서는 하드웨어, 성능, 데이터 품질 등 여러 현실적인 문제들을 고려해야 한다.

6.1 하드웨어 선정

  • 컴패니언 컴퓨터: nvblox의 GPU 가속 성능을 온전히 활용하기 위해서는 NVIDIA Jetson 시리즈(Jetson Orin NX, AGX Orin 등)가 가장 이상적인 온보드 컴퓨터이다.5 Raspberry Pi와 같은 저사양 SBC는 VSLAM과

nvblox를 동시에 실시간으로 처리하기에 연산 능력이 부족하다.3

  • 센서: isaac_ros_visual_slamnvblox_ros의 조합에는 고품질의 깊이 데이터를 제공하고, IMU 데이터와의 시간 동기화(timestamp synchronization)가 잘 이루어지는 스테레오 카메라(예: Intel RealSense D435i/D455, Stereolabs ZED 2i)가 매우 적합하다.1

6.2 성능 최적화 및 대역폭 관리

nvblox가 생성하는 3D 메시나 포인트 클라우드 데이터는 용량이 매우 크다.11 이를 무선 통신(Wi-Fi)을 통해 원격 GCS(Ground Control Station)로 실시간 전송하는 것은 통신 대역폭을 빠르게 고갈시켜 제어 신호 유실과 같은 심각한 문제를 야기할 수 있다.11 따라서, 모든 핵심 연산(VSLAM, nvblox 맵핑)은 반드시 드론에 탑재된 컴패니언 컴퓨터에서 수행되어야 한다. 원격 GCS로는 시각화를 위한 3D 메시의 업데이트 주기(max_mesh_update_hz)를 1Hz 이하로 대폭 낮추거나, 압축된 2D 맵 슬라이스와 같은 경량화된 데이터만을 선택적으로 전송하는 전략이 필수적이다.

6.3 고품질 자세 추정의 중요성

“Garbage In, Garbage Out” 원칙은 nvblox에 그대로 적용된다. nvblox가 생성하는 맵의 품질은 입력되는 자세 정보의 품질에 절대적으로 의존한다.4 VSLAM의 추정 오차가 누적(drift)되거나, 빠른 회전, 조명 변화, 특징점이 없는 환경 등으로 인해 추정에 실패하면, nvblox는 벽이 두 겹으로 보이거나 복도가 휘어 보이는 등 심하게 왜곡된 맵을 생성한다. 따라서, nvblox_ros를 성공적으로 적용하기 위한 선결 과제는 isaac_ros_visual_slam과 같은 고성능 VSLAM 시스템을 안정적으로 운영하고, 센서 캘리브레이션과 파라미터 튜닝을 통해 최대한 정확한 자세 정보를 확보하는 것이다.2

6.4 동적 환경 대응

실제 환경에는 사람, 차량 등 움직이는 객체들이 존재한다. mapping_type 파라미터를 dynamic 또는 people_segmentation으로 설정하면, nvblox는 딥러닝 기반의 의미론적 분할 마스크를 입력받아 움직이는 객체를 정적인 배경과 분리하여 처리할 수 있다.4 또한, 동적 맵에서는 한 번 장애물로 인식된 복셀이라도 시간이 지나면 점유 확률이 점차 감소하는 ‘점유 확률 감쇠(Occupancy Decay)’ 기능이 적용된다.4 이를 통해 드론은 이전에 사람이 지나갔던 공간을 다시 안전한 길로 인식하고 통과할 수 있게 된다.

궁극적으로, 실제 드론에 nvblox를 성공적으로 적용하는 것은 nvblox라는 단일 패키지의 문제가 아닌, 전체 시스템을 통합하는 문제이다. 고품질 센서, 안정적인 비행 제어기(FC), 고성능 온보드 컴퓨터, 정확한 VSLAM, 효율적인 nvblox 맵핑, 그리고 지능적인 경로 계획기가 유기적으로 결합되어야만 비로소 강력한 자율 비행 시스템이 완성된다.3 각 구성 요소 간의 인터페이스(토픽, TF), 데이터 흐름, 연산 부하 분배 등을 종합적으로 고려하는 시스템 엔지니어링 관점의 접근이 핵심 성공 요인이다.

7. 결론

nvblox_ros는 NVIDIA GPU 가속 기술을 바탕으로, 실시간 3D 환경 재구성과 경로 계획에 최적화된 ESDF 맵 생성을 가능하게 하는 강력한 ROS 2 패키지이다. 이는 자율 드론의 핵심 기술인 환경 인식 능력을 한 차원 높은 수준으로 끌어올리는 데 결정적인 역할을 한다.

본 안내서를 통해 분석한 nvblox_ros의 성공적인 통합을 위한 핵심 전략은 다음과 같이 요약할 수 있다.

  1. 견고한 개발 환경: Docker를 활용하여 복잡한 의존성 문제를 해결하고 안정적인 개발 및 배포 환경을 구축한다.
  2. 정확한 자세 추정: isaac_ros_visual_slam과 같은 고품질 VSLAM/VIO 시스템과의 안정적인 연동을 통해 ‘Garbage In, Garbage Out’ 문제를 방지한다.
  3. 전략적 파라미터 튜닝: 드론의 하드웨어 사양과 임무의 특성을 고려하여 voxel_size, 맵 업데이트 주기 등 핵심 파라미터를 최적화한다.
  4. 시뮬레이션 기반 검증: Isaac Sim을 적극적으로 활용하여 ‘Sim-to-Real’ 워크플로우를 구축하고, 실제 비행에 앞서 알고리즘과 시스템 통합을 충분히 검증한다.

앞으로 nvblox와 같은 GPU 가속 기반의 인식 라이브러리들은 ROS 2 로보틱스 생태계에서 점차 표준적인 구성 요소로 자리 잡을 것이다. 이는 실시간 3D 경로 계획, 동적 장애물에 대한 능동적 회피, 의미론적 정보를 포함한 풍부한 맵 구축 등, 지금까지 구현하기 어려웠던 더욱 지능적이고 정교한 드론 애플리케이션의 등장을 가속화할 것으로 전망된다.33

8. 참고 자료

  1. Nvblox — isaac_ros_docs documentation - NVIDIA Isaac ROS, https://nvidia-isaac-ros.github.io/concepts/scene_reconstruction/nvblox/index.html
  2. NVIDIA-ISAAC-ROS/isaac_ros_visual_slam: Visual SLAM/odometry package based on NVIDIA-accelerated cuVSLAM - GitHub, https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_visual_slam
  3. I need help building a drone using ROS - Reddit, https://www.reddit.com/r/ROS/comments/18snl2r/i_need_help_building_a_drone_using_ros/
  4. Tinker-Twins/NVIDIA-Isaac-ROS-Nvblox - GitHub, https://github.com/Tinker-Twins/NVIDIA-Isaac-ROS-Nvblox
  5. Isaac ROS Nvblox — isaac_ros_docs documentation, https://nvidia-isaac-ros.github.io/repositories_and_packages/isaac_ros_nvblox/index.html
  6. nvidia-isaac/nvblox: A GPU-accelerated TSDF and ESDF library for robots equipped with RGB-D cameras. - GitHub, https://github.com/nvidia-isaac/nvblox
  7. nvblox: GPU-Accelerated Incremental Signed Distance Field Mapping - arXiv, https://arxiv.org/html/2311.00626v2
  8. VoxelCache: Accelerating Online Mapping in Robotics and 3D Reconstruction Tasks, https://www.researchgate.net/publication/367481067_VoxelCache_Accelerating_Online_Mapping_in_Robotics_and_3D_Reconstruction_Tasks
  9. GLSL truncated signed distance representation (TSDF) implementation - Stack Overflow, https://stackoverflow.com/questions/40560801/glsl-truncated-signed-distance-representation-tsdf-implementation
  10. VDBFusion: Flexible and Efficient TSDF Integration of Range Sensor Data - PMC, https://pmc.ncbi.nlm.nih.gov/articles/PMC8838740/
  11. arplaboratory/nvblox: Repo for the modified NvBlox … - GitHub, https://github.com/arplaboratory/nvblox
  12. naraharip2017/ros_tsdf - GitHub, https://github.com/naraharip2017/ros_tsdf
  13. NVIDIA-ISAAC-ROS/isaac_ros_cumotion: NVIDIA-accelerated packages for arm motion planning and control - GitHub, https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_cumotion
  14. How Does ESDF Generation Work? — voxblox documentation - Read the Docs, https://voxblox.readthedocs.io/en/latest/pages/How-Does-ESDF-Generation-Work.html
  15. How to run nvblox sample with isaac_sim-2022.2.0? - Isaac ROS …, https://forums.developer.nvidia.com/t/how-to-run-nvblox-sample-with-isaac-sim-2022-2-0/237806
  16. Multiple cost map with Isaac ROS Nvblox - NVIDIA Developer Forums, https://forums.developer.nvidia.com/t/multiple-cost-map-with-isaac-ros-nvblox/294846
  17. leggedrobotics/glimpse_nvblox_ros1: Static fork from Nvidia’s Nvblox repo. Converted to ROS-1 and adapted for 3d-LiDAR generated depth images - GitHub, https://github.com/leggedrobotics/glimpse_nvblox_ros1
  18. nvblox_ros — isaac_ros_docs documentation - NVIDIA Isaac ROS, https://nvidia-isaac-ros.github.io/repositories_and_packages/isaac_ros_nvblox/nvblox_ros/index.html
  19. isaac_ros_nvblox/nvblox_ros/include/nvblox_ros/nvblox_node.hpp at main · NVIDIA-ISAAC-ROS/isaac_ros_nvblox - GitHub, https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_nvblox/blob/main/nvblox_ros/include/nvblox_ros/nvblox_node.hpp
  20. Isaac_ros_nvblox obtacle detection issue - Isaac ROS - NVIDIA Developer Forums, https://forums.developer.nvidia.com/t/isaac-ros-nvblox-obtacle-detection-issue/287977
  21. Parameters — ROS 2 Documentation: Humble documentation, https://docs.ros.org/en/humble/Concepts/Basic/About-Parameters.html
  22. ROS2 YAML For Parameters - The Robotics Back-End, https://roboticsbackend.com/ros2-yaml-params/
  23. Isaac ROS VSLAM and Nvblox - how to change internal parameters, https://forums.developer.nvidia.com/t/isaac-ros-vslam-and-nvblox-how-to-change-internal-parameters/306635
  24. Changing launch parameters for nvblox realsense example - NVIDIA Developer Forums, https://forums.developer.nvidia.com/t/changing-launch-parameters-for-nvblox-realsense-example/336623
  25. Nvblox back projected depth compensation - Isaac ROS - NVIDIA Developer Forums, https://forums.developer.nvidia.com/t/nvblox-back-projected-depth-compensation/335183
  26. isaac_ros_nvblox — isaac_ros_docs documentation, https://nvidia-isaac-ros.github.io/repositories_and_packages/isaac_ros_nvblox/isaac_ros_nvblox/index.html
  27. Can not build ’nvblox ros ’issac ros nvblox - Isaac ROS - NVIDIA Developer Forums,